import { Ref } from "vue";
import { fabric } from "fabric";
import { Canvas } from "fabric/fabric-impl";
import OpenSeadragon from "openseadragon";

// 获取实际比例
const getActualNum = (slideInfo: Ref<{
    Magnification: string;
    Mpp: string;
    Width: string;
    Height: string;
}>, viewer: Ref<any>) => {
    const originImgWidth = Number(slideInfo.value?.Width);
    const Magnification = Number(slideInfo.value?.Magnification) || 20;
    const containerWidth = Number(viewer.value.container?.clientWidth);
    return originImgWidth / Magnification / containerWidth;
};

export const getMarkCanvasObj = (tool: string, id: number, color: string, result: string, viewer: Ref<any>, slideInfo: Ref<{
    Magnification: string;
    Mpp: string;
    Width: string;
    Height: string;
}>, fabricCanvas: Ref<Canvas | null>) => {
    console.log(window.frabicCanvas.calcOffset().viewportTransform, '===2');
    let markCanvasObj: any = null;
    const newResult = JSON.parse(result || '{}');
    console.log(newResult, 'newResult');
    const { data, acZoom, version } = newResult;
    const a = function () {
        console.log(window.frabicCanvas.calcOffset().viewportTransform, '偏移量');
    }
    const newData = {
        point3: a(),
        point1: { ...changePoint(viewer, data.point1) },
        point2: { ...changePoint(viewer, data.point2) }
    }
    
    // 获取实际倍率
    const nzoom = viewer.value.viewport.getZoom() / getActualNum(slideInfo, viewer);
    if (tool === 'RECTANGLE') {
        const zoom = viewer.value.viewport.getZoom();
        markCanvasObj = new fabric.Rect({
            top: Math.min(newData.point1.y, newData.point2.y),
            left: Math.min(newData.point1.x, newData.point2.x),
            width: Math.abs(newData.point1.x - newData.point2.x),
            height: Math.abs(newData.point1.y - newData.point2.y),
            cornerColor: '#1FFF79',
            borderColor: '#1FFF79',
            cornerSize: 10,
            type: 'rect',
            stroke: color,
            strokeWidth: 1,
            fill: "rgba(255, 255, 255, 0)",
            hasControls: true,
            hasBorders: false,
            transparentCorners: false, 
            perPixelTargetFind: true,
            lockRotation: true,
            selectable: true,
            centeredScaling: false,
            strokeUniform: true,
            originX: 'left',
            originY: 'top'
        })
        window.frabicCanvas && (window.frabicCanvas.skipTargetFind = false);
        window.frabicCanvas && (window.frabicCanvas.selection = true);
        window.frabicCanvas && (window.frabicCanvas.selectionColor = 'transparent');
        window.frabicCanvas && (window.frabicCanvas.selectionBorderColor = color);
        markCanvasObj.set('id', id);
        markCanvasObj.set('acZoom', acZoom);
    }
    if (tool === 'ELLIPSE') {
        let rx = Math.abs(newData.point1.x - newData.point2.x) / 2;
        let ry = Math.abs(newData.point1.y - newData.point2.y) / 2;
        let top = newData.point2.y > newData.point1.y ? newData.point1.y : newData.point1.y - ry * 2;
        let left = newData.point2.x > newData.point1.x ? newData.point1.x :  newData.point1.x - rx * 2;
        rx = (rx / acZoom) * nzoom;
        ry = (ry / acZoom) * nzoom;
        top = (top / acZoom) * nzoom;
        left = (left / acZoom) * nzoom;
        markCanvasObj = new fabric.Ellipse({
            top,
            left,
            rx,
            ry,
            cornerColor: '#1FFF79',
            borderColor: '#1FFF79',
            cornerSize: 10,
            type: 'ellipse',
            stroke: color,
            strokeWidth: 1,
            fill: "rgba(255, 255, 255, 0)",
            hasControls: true,
            hasBorders: false,
            transparentCorners: false,
            perPixelTargetFind: true,
            lockRotation: true,
            centeredScaling: false,
            strokeUniform: true,
            originX: 'left',
            originY: 'top'
        })
        window.frabicCanvas && (window.frabicCanvas.skipTargetFind = false);
        window.frabicCanvas && (window.frabicCanvas.selection = true);
        window.frabicCanvas && (window.frabicCanvas.selectionColor = 'transparent');
        window.frabicCanvas && (window.frabicCanvas.selectionBorderColor = color);
        markCanvasObj.set('id', id);
        markCanvasObj.set('acZoom', acZoom);
    }
    window.frabicCanvas?.add(markCanvasObj!).renderAll();
    return markCanvasObj;
}

// 鼠标节流
export const throttle = (func: any, wait: number) => {
    var previous = 0;
    return function(this: any) {
        let now = Date.now();
        let context = this;
        let args = arguments;
        if (now - previous > wait) {
            func.apply(context, args);
            previous = now;
        }
    }
}

// 鼠标防抖
export const debounce = (func: any, wait: number) => {
    let timeout: string | number | NodeJS.Timeout | undefined;
    return function (this: any) {
        const context = this;
        const args = [...arguments];
        if (timeout) clearTimeout(timeout);
        timeout = setTimeout(() => {
        func.apply(context, args)
        }, wait);
    }
}

// 处理尺子回显逻辑
export const getLocalStroage = (result: any, viewer: Ref<any>, fabricCanvas: Ref<Canvas | null>, slideInfo: Ref<{
    Magnification: string;
    Mpp: string;
    Width: string;
    Height: string;
}>) => {
    // 获取实际倍率
    const nzoom = viewer.value.viewport.getZoom() / getActualNum(slideInfo, viewer);
    // 将每一项的组解散并根据实际倍率重新计算
    // const canvasObject = new fabric.Line([item.data.point1.x, item.data.point1.y, item.data.point2.x, item.data.point2.y], {
    const canvasObject = new fabric.Line([result.data.point1.x / result.acZoom * nzoom, result.data.point1.y / result.acZoom * nzoom, result.data.point2.x / result.acZoom * nzoom, result.data.point2.y / result.acZoom * nzoom], {
        stroke: '#448E97',
        cornerColor: '#1FFF79',
        borderColor: '#1FFF79',
        cornerSize: 10,
        strokeWidth: 1,
        fill: "rgba(255, 255, 255, 0)",
        hasControls: true,
        hasBorders: false,
        transparentCorners: false, 
        perPixelTargetFind: true,
        lockRotation: true,
        selectable: true,
        centeredScaling: false,
        strokeUniform: true,
        originX: 'left',
        originY: 'top'
        // id: result.id,
        // acZoom: result.acZoom
    });
    const width = (result.acWidth / result.acZoom) * nzoom;
    const height = (result.acHeight / result.acZoom) * nzoom;
    const lineLength = Math.round(Math.sqrt(width * width + height * height) * 100) / 100;
    const top = Math.min(result.data.point1.y, result.data.point2.y);
    const left = Math.min(result.data.point1.x, result.data.point2.x);
    const textObject = new fabric.Text(`${lineLength}mm`, {
        top: top / result.acZoom * nzoom,
        left: left / result.acZoom * nzoom + (left / result.acZoom * nzoom / 5),
        fontSize: 20,
        originX: "center",
        originY: "center",
        // angle: Math.abs(result.angle)
    });
    const group = new fabric.Group([canvasObject, textObject], { 
        type: 'group',
        borderColor: 'transparent', // 边框颜色
        cornerColor: 'transparent', // 控制角颜色
        cornerSize: 10, // 控制角大小
        // 控制器是否为填充 true为透明 false为填充
        transparentCorners: false,
        hasControls: false,
        lockScalingX: true,
        lockScalingY: true,
        lockRotation: true,
        lockMovementX: true,
        lockMovementY: true,
        perPixelTargetFind: true
    });
    window.frabicCanvas?.add(group!).renderAll();
}

// 坐标数据转换
export const changePoint = (viewer: Ref<any>, point: { x: number, y: number }, type: boolean = false): { x: number, y: number } => {
    let result = {
        x: 0,
        y: 0
    };
    console.log(window.frabicCanvas.calcOffset().viewportTransform, 'offset');
    // 记录画布鼠标按下时的x偏移量
    const offsetX = window.frabicCanvas.calcOffset().viewportTransform[4];
    // 记录画布鼠标按下时的y偏移量
    const offsetY = window.frabicCanvas.calcOffset().viewportTransform[5];

    const boundsNoRotate = viewer.value.viewport.getBoundsNoRotate(true);
    const boundsNoRotatePoint = new OpenSeadragon.Point(boundsNoRotate.x, boundsNoRotate.y);
    const boundsNoRotateWindowPoint = viewer.value.viewport.viewportToWindowCoordinates(boundsNoRotatePoint);
    if (type) {
        point.x = point.x + offsetX + boundsNoRotateWindowPoint.x;
        point.y = point.y + offsetY + boundsNoRotateWindowPoint.y;
        point.x = Math.round(point.x);
        point.y = Math.round(point.y);
        const newPoint = new OpenSeadragon.Point(point.x, point.y)
        const imgPoint = viewer.value.viewport.windowToImageCoordinates(newPoint);
        result = imgPoint;
    } else {
        const openPoint = new OpenSeadragon.Point(point.x , point.y);
        const windowPoint = viewer.value.viewport.imageToWindowCoordinates(openPoint);
        windowPoint.x = windowPoint.x - boundsNoRotateWindowPoint.x - offsetX;
        windowPoint.y = windowPoint.y - boundsNoRotateWindowPoint.y - offsetY;
        windowPoint.x = Math.round(windowPoint.x);
        windowPoint.y = Math.round(windowPoint.y);
        result = windowPoint;
    }
    return result;
}